#include "EventLoopThreadPoll.h"
#include "EventLoop.h"
#include "EventLoopThread.h"

#include <memory>

EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, const std::string& nameArg)
    : baseLoop_(baseLoop)
    , name_(nameArg)
    , started_(false)
    , numThreads_(0)
    , next_(0)
{
}

EventLoopThreadPool::~EventLoopThreadPool()
{
    // Don't delete loop, it's stack variable
    /**
     * 线程里绑定的loop，都是栈上的对象
     * EventLoopThread::threadFunc()函数是不会出}的，loop.loop()会一直循环
     * 除非底层不工作了，返回了，出了}对象会自动析构的
     * EventLoop loop是在线程函数的线程栈上创建的
     */
}

void EventLoopThreadPool::start(const ThreadInitCallback& cb)
{
    started_ = true;

    for(int i=0; i<numThreads_; ++i)
    {
        char buf[name_.size() + 32];
        // 底层线程的命名规则 线程池名字+序号下标
        snprintf(buf, sizeof buf, "%s%d", name_.c_str(), i);
        EventLoopThread *t = new EventLoopThread(cb, buf);
        threads_.push_back(std::unique_ptr<EventLoopThread>(t));
        loops_.push_back(t->startLoop());  // 底层创建线程，绑定一个新的EventLoop，并返回该loop的地址
    }

    // 整个服务端只有一个线程，运行着baseloop_
    if(numThreads_ == 0 && cb)
    {
        cb(baseLoop_);
    }
}

// 如果工作在多线程，baseLoop_(相当于mainloop了）会默认以轮询的方式分配channel给subloop
EventLoop* EventLoopThreadPool::getNextLoop()
{
    EventLoop* loop = baseLoop_;  // mainloop

    if(!loops_.empty())  // 如果没有通过setThreadNum设置工作线程数量，那么所有事情都在mainloop上完成
    {
        // 轮询工作线程，获取下一个处理事件的loop
        loop = loops_[next_];
        ++next_;
        if(next_ >= loops_.size())
        {
            next_ = 0;
        }
    }

    return loop;
}

std::vector<EventLoop*> EventLoopThreadPool::getAllLoops()
{
    if(loops_.empty())  // 没有创建工作线程，只有baseLoop_
    {
        return std::vector<EventLoop*>(1, baseLoop_);
    }
    else
    {
        return loops_;
    }
}